package cn.itsource.org.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import cn.itsource.basic.config.BusinessException;
import cn.itsource.basic.service.impl.BaseServiceImpl;
import cn.itsource.basic.util.AjaxResult;
import cn.itsource.basic.util.MobileMessageUtil;
import cn.itsource.basic.util.RedisService;
import cn.itsource.org.domain.User;
import cn.itsource.org.domain.UserInfo;
import cn.itsource.org.mapper.UserMapper;
import cn.itsource.org.query.UserQuery;
import cn.itsource.org.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

@Service
@Slf4j //开启日志
//Propagation.SUPPORTS:支持别人事务
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class UserServiceImpl extends BaseServiceImpl<User, UserQuery> implements IUserService {
    //基础查询由继承得到

    @Autowired
    private RedisService redisService;

    @Autowired
    private UserMapper userMapper;

    @Override
    public AjaxResult userLogin(User user) {
        //1.根据user的username查询user对象,如果不存在,抛异常
        User dbUser = userMapper.findByUsername(user);
        if (dbUser == null) {
            throw new BusinessException("用户名或密码不匹配111111111");
        }

        //2.根据前端给的密码,加密加盐   和  数据库的密码比对 如果不通过,抛异常
        String pagePwd = MD5.create().setSalt(dbUser.getSalt().getBytes()).digestHex(user.getPassword());
        if (!StrUtil.equals(pagePwd,dbUser.getPassword())){
            throw new BusinessException("用户名或密码不匹配33333333333");
        }

        //3.准备token,存redis  value:用户信息UserInfo对象  通用对象, 拦截器也可以通用
        String token = IdUtil.fastSimpleUUID();
        UserInfo userInfo = BeanUtil.copyProperties(dbUser, UserInfo.class);
        userInfo.setToken(token);
        //设置用户id
        userInfo.setUserId(dbUser.getId());

        redisService.setStringKeyAndValue(token,userInfo,30);

        //4.返回userInfo信息
        return AjaxResult.createSuccess(userInfo);
    }


    @Override
    public AjaxResult checkPhone(String phone) {
        //1.验证手机号合法性
        boolean mobile = Validator.isMobile(phone);
        if (!mobile){
            throw new BusinessException("手机号有误,请重新输入...");
        }

        //2.校验手机号是否被注册过 select * from t_user where phone = #{phone}
        User user = userMapper.findByPhone(phone);

        if (user != null){
            throw new BusinessException("用户已经注册过了...");
        }

        return AjaxResult.createSuccess("手机号验证通过");

    }


    /**
     * 发送验证码
     * @param phone
     * @return
     */
    @Override
    public AjaxResult sendMobileCode(String phone, HttpServletRequest request) {
        //验证手机号
        boolean mobile = Validator.isMobile(phone);
        if (!mobile){
            throw new BusinessException("手机号有误,请重新输入...");
        }

        //2.校验手机号是否被注册过
//        User user = userMapper.findByPhone(phone);
//
//        if (user != null){
//            throw new BusinessException("用户已经注册过了...");
//        }

//        //3.拦截同一个ip一直获取验证码  //user/sendMobileCode/177255555554  ip user/sendMobileCode
//        String s = request.getRemoteAddr() + request.getRequestURI();
//
//        String res = redisService.getKeyObjectValue(s, String.class);
//        if (res != null){ //如果redis里面有数据，代表你访问过于频繁
//            throw new BusinessException("获取验证码过于频繁...");
//        }
//        //存ip到redis中,保持1分钟,1分钟内重复获取抛出上面的异常
//        redisService.setStringKeyAndValue(s,phone,1);

        //4.生成验证码,保存到redis 5分钟
        String code = RandomUtil.randomNumbers(4);
        //phone:手机号  code:验证码
        redisService.setStringKeyAndValue(phone,code,5);
        //[宠物乐园验证码]:1905,手机号:17799996666
        log.info("[宠物乐园验证码]:{},手机号:{}",code,phone);

        //调用发送验证码的服务 打印知道存到redis里面的验证码就行了,不发送
        //MobileMessageUtil.sendMessage(phone,code);

        return AjaxResult.createSuccess("发送验证码成功");
    }

    @Override
    @Transactional
    public AjaxResult registerUser(User user) {
        //自己去比对两次密码
        if (!StringUtils.equals(user.getPassword(), user.getConfigPassword())) {
            throw new BusinessException("两次密码不一致");
        }

        //验证手机号
        boolean mobile = Validator.isMobile(user.getPhone());
        if (!mobile){
            throw new BusinessException("手机号有误,请重新输入...");
        }

        //2.校验手机号是否被注册过
        User dbUser = userMapper.findByPhone(user.getPhone());

        if (dbUser != null){
            throw new BusinessException("用户已经注册过了...");
        }
        //1.从redis里面获取验证码，如果获取不到，过期了
        String redisCode = redisService.getKeyObjectValue(user.getPhone());

        //1.1没拿到异常
        /*if (StrUtil.isBlank(redisCode)){
            throw   new BusinessException("验证码过期了");
        } 这个是全写，下面是java8新写法 */
        Optional.ofNullable(redisCode).orElseThrow(() -> new BusinessException("验证码过期了"));

        //2.把你传递的验证码和redis里面比对，如果比对不过，代表验证码错误
        if (!StrUtil.equals(user.getCode(),redisCode)){
            throw new BusinessException("验证码错误...");
        }

        //3.入库 （注意：加盐加密）
        user.initPwd();
        userMapper.insertSelective(user);

        return AjaxResult.createSuccess();
    }



    public static void main(String[] args) {
        log.info("[宠物乐园验证码]:{},手机号:{}","111","17736565658");//推荐

        log.info("[宠物乐园验证码]:"+"123213"+",手机号:"+"1772135450");
        //[宠物乐园验证码]:111,手机号:17736565658


        boolean equals = StringUtils.equals(null, null);
        System.out.println(equals);

    }


}
